<template>
	<div class='project-files'>
		<header>
			<ChooseFile
				multiple
				@change="changeFile"
			>
				<el-button>选择文件</el-button>
			</ChooseFile>
			<el-button
				class="upload-btn"
				type="primary"
				:loading="uploading"
				:disabled="!canUpload"
				@click="onclickUpload"
			>
				立即上传
			</el-button>
		</header>

		<!-- 文件列表 -->
		<div class="files">
			<div
				class="file"
				v-for="(file,i) in files"
				:key="file.id"
			>
				<div class="left">
					<div class="name">{{file.name}}</div>
					<div class="file-info">
						<!-- 价格 -->
						<span>
							<el-icon
								size="16px"
								color="#6782f1"
							>
								<Coin />
							</el-icon>
							{{file.price}}
						</span>
						<!-- 成果类型 -->
						<span>
							{{fileClassifyMsg(file.typeId)}}
						</span>
						<!-- 文件类型 -->
						<span>
							{{fileTypeMsg(file.fileType)}}
						</span>
					</div>
					<div class="process">
						<el-progress
							:percentage="file.progress"
							:status="fileProgressStatusMap[file.status]"
						/>
					</div>
				</div>
				<div
					v-if="!file.passed"
					class="right"
				>
					<el-icon size="20px">
						<Edit @click="setFile=file" />
					</el-icon>
					<el-icon
						class="delete-icon"
						style="margin-left: 10px;"
						size="20px"
						@click="onclickDelFile(i)"
					>
						<Delete />
					</el-icon>
				</div>
			</div>
		</div>
		<SetFile
			v-if="setFile"
			:file="setFile"
			:awardLevel="props.project.awardLevel||11"
			@updateFile="updateFile"
		/>
	</div>
</template>

<script setup lang="ts">
import { ref, defineProps } from 'vue'
import { computed } from '@vue/reactivity'
import { Edit, Coin, Delete } from '@element-plus/icons-vue'
import {
  getCompResources,
  getCourseResources,
  deleteResource,
  getFilePrice,
  putResource,
  getFilesSignature,
  getCourseFileSign,
  postResource
} from '@/api/project'
import type { ProjectType, ProjectFileType, CompProjectType, ProjectUploadFileType } from '@/modules/project'
import { formatFile, cosUpload } from '@/utils/file'
import { fileClassifyMsg, fileTypeMsg } from '@/utils/filter'
import { $confirm } from '@/utils/functions'
import ChooseFile from '@/components/ChooseFile/index.vue'
import SetFile from './SetFile.vue'

const props = defineProps<{
	projectType: ProjectType,
	project: CompProjectType
}>()

const setFile = ref<ProjectUploadFileType | null>(null)

/**
 * 初始化附件
 */
const files = ref<ProjectUploadFileType[]>([])
const loadFiles = async() => {
  const res = await typeMap.getApi({
    id: props.project.id,
    edit: true
  })
  files.value = res.data.map((item:ProjectFileType) => {
    return {
      id: item.id,
      name: item.name,
      size: '',
      typeId: item.typeId,
      fileType: item.fileType,
      progress: 100,
      status: 2,
      price: item.price,
      passed: item.passed
    }
  })
  console.log(files.value[ 0 ])
}
const fileProgressStatusMap = { // 附近状态map集合
  0: '',
  1: '',
  2: 'success',
  3: 'exception'
}

/**
 * 计算是否有上传的文件
 */
const canUpload = computed(() => !!files.value.find(item => item.status !== 2))
const uploading = ref(false)

/**
 * 选择文件，格式化内容后追加到数组中
 */
const changeFile = (e:File[] | null) => {
  if (!e) {
    return
  }
  e.forEach(async(item) => {
    const file = formatFile(item)
    if (props.projectType === 'courseDesign') { // 课设项目，typeId改成6
      file.typeId = 6
    } else if (props.projectType === 'competition') { // 比赛项目，计算推荐价格
      file.price = (await getFilePrice({
        awardLevel: props.project.awardLevel || 11,
        classifyId: file.typeId
      })).data
    }
    files.value.unshift(file)
    console.log(file)
  })
  setTimeout(() => {
    console.log(files.value[ 0 ])
  }, 1000)
}

/**
 * 更新文件
 */
const updateFile = (file:ProjectUploadFileType) => {
  const index = files.value.findIndex(item => item.id === file.id)
  files.value[ index ] = file
  /* 如果已经上传的，需要调用接口更新附件 */
  if (file.status === 2) {
    putResource(file.id, file)
  }
  setFile.value = null
}

/**
 * 点击删除文件
 */
const onclickDelFile = (i:number) => {
  $confirm('确认删除该附件?', () => {
    try {
      deleteResource(files.value[ i ].id)
      files.value.splice(i, 1)
    } catch (error) {
      console.log(error)
    }
  })
}

/**
 * 点击上传文件
 */
const onclickUpload = async() => {
  uploading.value = true
  try {
    const uploadFiles = files.value.filter(item => item.status !== 2)
    /* 获取签名 */
    const signs = await Promise.all(uploadFiles.map((file, i) => {
      const filename = `${ Date.now() }${ i }.${ file.suffix }`

      return typeMap.fileSign(props.project.id, filename)
    }))
    /* 上传文件，不管失败还是成功，都继续进行 */
    const upRes = await Promise.allSettled(signs.map((res, i) => {
      const file = uploadFiles[ i ]
      return file.raw
        ? cosUpload(file.raw, res.data, (progress:number) => {
          file.progress = progress
        })
        : {}
    }))
    console.log(upRes)
    const updateFiles = await Promise.all(upRes.map((res, i) => {
      const file = uploadFiles[ i ]

      /* 往数据库添加上传成功的文件 */
      if (res.status === 'fulfilled') {
        file.status = 2
        return postResource(props.project.id, {
          name: file.name,
          filename: res.value,
          price: file.price,
          typeId: file.typeId,
          fileType: file.fileType,
          discount: 0
        })
      } else { // 失败的文件进入失败状态
        file.status = 3
        return {}
      }
    }))

    /* 更新上传文件的id和通过状态 */
    updateFiles.forEach((res, i) => {
      const file = uploadFiles[ i ]

      file.id = res.data
      file.passed = typeMap.newFilePassed
    })
  } catch (err) {
    console.log(err)
  }
  uploading.value = false
}

const typeMap = {
  competition: {
    getApi: getCompResources,
    fileSign: getFilesSignature,
    newFilePassed: false,
  },
  courseDesign: {
    getApi: getCourseResources,
    fileSign: getCourseFileSign,
    newFilePassed: true
  }
}[ props.projectType ]
loadFiles()
</script>

<style lang="scss" scoped>
.project-files {
  header {
    .upload-btn {
      margin-left: 15px;
    }
  }

  .files {
    padding-top: 10px;

    .file {
      &:not(:last-of-type) {
        margin-bottom: 15px;
      }

      display: flex;
      align-items: center;
      width: 100%;
      padding: 10px;
      background-color: #ffffff;
      border-radius: $radiusMiddle;
      box-shadow: $shadow2;

      .left {
        flex: 1;

        .name {
          max-width: 550px;
        }

        .file-info {
          display: flex;
          padding: 5px;
          font-size: $sSmall;

          span {
            display: flex;
            align-items: center;
            margin-right: 10px;
          }
        }

        .process {
          min-width: 500px;
        }
      }

      .right {
        display: flex;
        align-items: center;

        .el-icon {
          cursor: pointer;

          &.delete-icon:hover {
            color: $red;
          }
        }
      }
    }
  }
}
</style>
